<?php
/**
 * 数独生成与求解类: 可删
 * 功能：生成完整数独，随机挖空，并验证唯一解
 */
class Sudoku {
    private $grid;         // 数独题目
    private $solution;     // 数独答案
    private $emptyCells;   // 挖空数量
    
    public function __construct($emptyCells = 50) {
        $this->emptyCells = min(55, max(30, $emptyCells));
        $this->generate();
    }
    
    // 生成数独主方法
    private function generate() {
        do {
            // 生成完整有效数独
            $this->grid = array_fill(0, 9, array_fill(0, 9, 0));
            $this->fillGrid();
            $this->solution = $this->grid;
            
            // 挖空创建谜题
            $this->removeCells();
            
            // 验证唯一解
        } while (!$this->hasUniqueSolution());
    }
    
    // 填充数独网格
    private function fillGrid() {
        $this->fillDiagonalBoxes();
        $this->fillRemaining(0, 3);
    }
    
    // 填充对角线上的3x3宫
    private function fillDiagonalBoxes() {
        for ($i = 0; $i < 9; $i += 3) {
            $this->fillBox($i, $i);
        }
    }
    
    // 填充单个3x3宫
    private function fillBox($row, $col) {
        $nums = range(1, 9);
        shuffle($nums);
        for ($i = 0; $i < 3; $i++) {
            for ($j = 0; $j < 3; $j++) {
                $this->grid[$row + $i][$col + $j] = array_pop($nums);
            }
        }
    }
    
    // 递归填充剩余格子
    private function fillRemaining($i, $j) {
        if ($j >= 9 && $i < 8) {
            $i++;
            $j = 0;
        }
        if ($i >= 9 && $j >= 9) {
            return true;
        }
        if ($i < 3) {
            if ($j < 3) $j = 3;
        } elseif ($i < 6) {
            if ($j == (int)($i / 3) * 3) $j += 3;
        } else {
            if ($j == 6) {
                $i++;
                $j = 0;
                if ($i >= 9) return true;
            }
        }
        
        for ($num = 1; $num <= 9; $num++) {
            if ($this->isSafe($i, $j, $num)) {
                $this->grid[$i][$j] = $num;
                if ($this->fillRemaining($i, $j + 1)) {
                    return true;
                }
                $this->grid[$i][$j] = 0;
            }
        }
        return false;
    }
    
    // 检查数字是否安全
    private function isSafe($row, $col, $num) {
        return $this->unusedInRow($row, $num) &&
               $this->unusedInCol($col, $num) &&
               $this->unusedInBox($row - $row % 3, $col - $col % 3, $num);
    }
    
    // 检查行
    private function unusedInRow($row, $num) {
        for ($col = 0; $col < 9; $col++) {
            if ($this->grid[$row][$col] == $num) {
                return false;
            }
        }
        return true;
    }
    
    // 检查列
    private function unusedInCol($col, $num) {
        for ($row = 0; $row < 9; $row++) {
            if ($this->grid[$row][$col] == $num) {
                return false;
            }
        }
        return true;
    }
    
    // 检查宫
    private function unusedInBox($boxStartRow, $boxStartCol, $num) {
        for ($row = 0; $row < 3; $row++) {
            for ($col = 0; $col < 3; $col++) {
                if ($this->grid[$row + $boxStartRow][$col + $boxStartCol] == $num) {
                    return false;
                }
            }
        }
        return true;
    }
    
    // 随机挖空
    private function removeCells() {
        $cells = [];
        for ($i = 0; $i < 9; $i++) {
            for ($j = 0; $j < 9; $j++) {
                $cells[] = [$i, $j];
            }
        }
        
        shuffle($cells);
        $removed = 0;
        
        foreach ($cells as $cell) {
            if ($removed >= $this->emptyCells) break;
            
            $row = $cell[0];
            $col = $cell[1];
            $backup = $this->grid[$row][$col];
            $this->grid[$row][$col] = 0;
            
            $removed++;
        }
    }
    
    // 验证唯一解
    private function hasUniqueSolution() {
        $tempGrid = $this->copyGrid($this->grid);
        $solutions = 0;
        $this->countSolutions(0, 0, $solutions, $tempGrid);
        return $solutions == 1;
    }
    
    // 计算解的数量
    private function countSolutions($row, $col, &$count, $grid) {
        if ($count > 1) return; // 发现多解立即退出
        
        if ($row == 9) {
            $count++;
            return;
        }
        
        if ($grid[$row][$col] != 0) {
            $nextRow = $col == 8 ? $row + 1 : $row;
            $nextCol = $col == 8 ? 0 : $col + 1;
            $this->countSolutions($nextRow, $nextCol, $count, $grid);
            return;
        }
        
        for ($num = 1; $num <= 9; $num++) {
            if ($this->isSafeForGrid($row, $col, $num, $grid)) {
                $grid[$row][$col] = $num;
                $nextRow = $col == 8 ? $row + 1 : $row;
                $nextCol = $col == 8 ? 0 : $col + 1;
                $this->countSolutions($nextRow, $nextCol, $count, $grid);
                if ($count > 1) return; // 发现多解立即退出
                $grid[$row][$col] = 0;
            }
        }
    }
    
    // 检查数字在指定网格中是否安全
    private function isSafeForGrid($row, $col, $num, $grid) {
        // 检查行
        for ($c = 0; $c < 9; $c++) {
            if ($grid[$row][$c] == $num) return false;
        }
        
        // 检查列
        for ($r = 0; $r < 9; $r++) {
            if ($grid[$r][$col] == $num) return false;
        }
        
        // 检查宫
        $boxRow = $row - $row % 3;
        $boxCol = $col - $col % 3;
        for ($r = 0; $r < 3; $r++) {
            for ($c = 0; $c < 3; $c++) {
                if ($grid[$boxRow + $r][$boxCol + $c] == $num) return false;
            }
        }
        
        return true;
    }
    
    // 复制网格
    private function copyGrid($grid) {
        $newGrid = [];
        foreach ($grid as $row) {
            $newGrid[] = $row;
        }
        return $newGrid;
    }
    
    public function getPuzzle() {
        return $this->grid;
    }
    
    public function getSolution() {
        return $this->solution;
    }
    
    public function getEmptyCellsCount() {
        return $this->emptyCells;
    }
    
    // 获取81位数字字符串
    public function getPuzzleString() {
        $str = '';
        foreach ($this->grid as $row) {
            $str .= implode('', $row);
        }
        return $str;
    }
    
    // 获取答案81位数字字符串
    public function getSolutionString() {
        $str = '';
        foreach ($this->solution as $row) {
            $str .= implode('', $row);
        }
        return $str;
    }
}

// 处理表单提交
$emptyCells = 50; // 默认值
if (isset($_GET['difficulty'])) {
    if ($_GET['difficulty'] == 'random') {
        $emptyCells = rand(38, 50);
    } elseif (is_numeric($_GET['difficulty'])) {
        $emptyCells = min(60, max(30, (int)$_GET['difficulty']));
    } elseif ($_GET['difficulty'] == 'easy') {
        $emptyCells = rand(30, 40);
    } elseif ($_GET['difficulty'] == 'medium') {
        $emptyCells = rand(41, 50);
    } elseif ($_GET['difficulty'] == 'hard') {
        $emptyCells = rand(51, 60);
    }
}

$sudoku = new Sudoku($emptyCells);
$puzzle = $sudoku->getPuzzle();
$solution = $sudoku->getSolution();
$puzzleStr = $sudoku->getPuzzleString();
$solutionStr = $sudoku->getSolutionString();
?>
<!DOCTYPE html>
<html lang="zh-CN">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>数独生成器</title>
    <style>
        body {
            font-family: "Microsoft YaHei", Arial, sans-serif;
            max-width: 900px;
            margin: 0 auto;
            padding: 20px;
            color: #333;
        }
        
        .sudoku-container {
            display: flex;
            flex-wrap: wrap;
            justify-content: space-between;
            margin-bottom: 30px;
            gap: 20px;
        }
        
        .sudoku-grid {
            border: 3px solid #333;
            display: grid;
            grid-template-columns: repeat(9, 1fr);
            grid-template-rows: repeat(9, 1fr);
            width: 100%;
            max-width: 450px;
            aspect-ratio: 1/1;
        }
        
        .cell {
            border: 1px solid #999;
            display: flex;
            align-items: center;
            justify-content: center;
            font-size: 24px;
            font-weight: bold;
            background-color: #fff;
            position: relative;
        }
        
        .cell:nth-child(3n) {
            border-right: 2px solid #333;
        }
        
        .cell:nth-child(9n) {
            border-right: none;
        }
        
        .sudoku-grid > div:nth-child(n+19):nth-child(-n+27),
        .sudoku-grid > div:nth-child(n+46):nth-child(-n+54) {
            border-bottom: 2px solid #333;
        }
        
        /* 题目样式 */
        .puzzle .cell.filled {
            color: #1a73e8; /* 蓝色题目数字 */
            background-color: #f8f9fa;
        }
        
        /* 答案样式 */
        .solution .cell {
            color: #34a853; /* 绿色答案数字 */
            background-color: #f8f9fa;
        }
        
        .solution .cell.filled {
            color: #1a73e8; /* 蓝色题目数字 */
            font-weight: normal;
        }
        
        .solution .cell.solved {
            color: #34a853; /* 绿色解答数字 */
            font-weight: bold;
        }
        
        .empty {
            color: transparent;
        }
        
        .controls {
            margin-bottom: 20px;
            padding: 15px;
            background-color: #f5f5f5;
            border-radius: 5px;
        }
        
        select, button {
            padding: 8px 12px;
            font-size: 16px;
            margin-right: 10px;
            border: 1px solid #ddd;
            border-radius: 4px;
        }
        
        button {
            background-color: #1a73e8;
            color: white;
            border: none;
            cursor: pointer;
        }
        
        button:hover {
            background-color: #1765cc;
        }
        
        button.copy-btn {
            background-color: #fbbc04;
            margin-top: 10px;
        }
        
        button.copy-btn:hover {
            background-color: #e9ab03;
        }
        
        h1, h2 {
            margin-top: 0;
            color: #1a73e8;
        }
        
        .note {
            font-size: 14px;
            color: #666;
            margin-top: 5px;
        }
        
        .data-box {
            margin-top: 15px;
            padding: 10px;
            background-color: #f8f9fa;
            border-radius: 4px;
            font-family: monospace;
            word-break: break-all;
        }
        
        @media (max-width: 768px) {
            .sudoku-container {
                flex-direction: column;
                align-items: center;
            }
        }
    </style>
</head>
<body>
    <h1>数独生成器</h1>
    
    <div class="controls">
        <form method="get">
            <label for="difficulty">难度设置：</label>
            <select id="difficulty" name="difficulty">
                <option value="random" <?php echo isset($_GET['difficulty']) && $_GET['difficulty'] == 'random' ? 'selected' : ''; ?>>随机难度</option>
                <?php for($i = 38; $i <= 60; $i++): ?>
                    <option value="<?php echo $i; ?>" <?php echo isset($_GET['difficulty']) && $_GET['difficulty'] == $i ? 'selected' : ''; ?>>
                        <?php echo $i; ?> 个空格
                    </option>
                <?php endfor; ?>
            </select>
            <button type="submit">生成数独</button>
        </form>
        <p class="note">当前数独：<?php echo $emptyCells; ?> 个空格 (难度: <?php 
            if ($emptyCells <= 40) echo '简单';
            elseif ($emptyCells <= 50) echo '中等';
            else echo '困难';
        ?>)</p>
    </div>
    
    <div class="sudoku-container">
        <div class="puzzle">
            <h2>数独题目</h2>
            <div class="sudoku-grid">
                <?php 
                $index = 0;
                for ($i = 0; $i < 9; $i++): 
                    for ($j = 0; $j < 9; $j++): 
                        $val = $puzzle[$i][$j];
                        $isFilled = $val != 0;
                ?>
                    <div class="cell <?php echo $isFilled ? 'filled' : 'empty'; ?>" 
                         data-index="<?php echo $index; ?>"
                         data-value="<?php echo $val; ?>">
                        <?php echo $isFilled ? $val : '&nbsp;'; ?>
                    </div>
                <?php 
                    $index++;
                    endfor; 
                endfor; 
                ?>
            </div>
            
            <div class="data-box">
                <p>81位数字格式 (0表示空格):</p>
                <div id="puzzle-data"><?php echo $puzzleStr; ?></div>
                <button class="copy-btn" onclick="copyToClipboard('puzzle-data')">复制题目数据</button>
            </div>
        </div>
        
        <div class="solution">
            <h2>数独答案</h2>
            <div class="sudoku-grid">
                <?php 
                $index = 0;
                for ($i = 0; $i < 9; $i++): 
                    for ($j = 0; $j < 9; $j++): 
                        $puzzleVal = $puzzle[$i][$j];
                        $solutionVal = $solution[$i][$j];
                        $isFilled = $puzzleVal != 0;
                ?>
                    <div class="cell <?php echo $isFilled ? 'filled' : 'solved'; ?>" 
                         data-index="<?php echo $index; ?>"
                         data-value="<?php echo $solutionVal; ?>">
                        <?php echo $solutionVal; ?>
                    </div>
                <?php 
                    $index++;
                    endfor; 
                endfor; 
                ?>
            </div>
            
            <div class="data-box">
                <p>81位数字格式 (包含题目和答案):</p>
                <div id="solution-data"><?php echo $solutionStr; ?></div>
                <button class="copy-btn" onclick="copyToClipboard('solution-data')">复制完整答案</button>
            </div>
        </div>
    </div>
    
    <script>
        // 兼容性良好的复制函数
        function copyToClipboard(elementId) {
            const element = document.getElementById(elementId);
            const text = element.innerText;
            
            // 创建临时textarea
            const textarea = document.createElement('textarea');
            textarea.value = text;
            textarea.style.position = 'fixed';  // 防止页面滚动
            document.body.appendChild(textarea);
            textarea.select();
            
            try {
                // 执行复制命令
                const successful = document.execCommand('copy');
                const msg = successful ? '复制成功!' : '复制失败';
                alert(msg);
            } catch (err) {
                alert('复制错误: ' + err);
            }
            
            // 清理
            document.body.removeChild(textarea);
        }
        
        // 为移动端添加点击反馈
        document.querySelectorAll('.cell').forEach(cell => {
            cell.addEventListener('click', function() {
                this.style.backgroundColor = '#e8f0fe';
                setTimeout(() => {
                    this.style.backgroundColor = '';
                }, 200);
            });
        });
    </script>
</body>
</html>